/**
 * gun.sprite.js
 *
 * @author http://www.yangkun.pe.kr
 * @version 1.0
 * @license MIT-style license.
 */
if (!$type(gun)) var gun = {};
if (!$type(gun.sprite)) {

	gun.sprite = {};

	gun.sprite.Basic = new Class({
		Implements: [Events, Options],
		options: {
			sprite: null,
			frameSize: [0,0],
			movies: {'default':[1,1]},
			frames: null,
			framesPerMovie: 1,
			initMovie: 'default',
			initFrame: 1,
			wrap: false
		},
		initialize: function(element, options) {
			this.setOptions(options);
			this.element = $(element);
			if ($chk(this.options.sprite)) this.setSprite(this.options.sprite);
			this.element.setStyles({'width': this.options.frameSize[0], 'height': this.options.frameSize[1], 'overflow':'hidden'});
			this.setMovies(this.options.movies);
			this.setMovie(this.options.initMovie);
			this.goto(this.options.initFrame);
		},
		setSprite: function(sprite, movies, frame) {
			this.element.setStyle('background-image', 'url(' + sprite + ')');
			if ($chk(movies)) this.setMovies(movies);
			if ($chk(frame)) this.goto(frame);
		},
		setMovies: function(movies, moveFirstFrame) {
			if ($type(movies) == 'number') {
				var moviesObj = {};
				for (var i = 0; i < movies; i++) moviesObj['movie' + (i+1)] = [i+1,1];
				this.movies = $H(moviesObj);
			} else {
				this.movies = $H(movies);
			}
			if (moveFirstFrame) this.goto(1);
		},
		setMovie: function(movie, moveFirstFrame) {
			if ($type(movie) == 'string' && this.movies.has(movie)) {
				this.movie = movie;
			} else if ($type(movie) == 'number') {
				var keys = this.movies.getKeys();
				this.movie = keys[movie - 1];
			} else {
				this.fireEvent('ERROR', ['invalid movie']);
			}
			if (moveFirstFrame) this.goto(1);
		},
		setFrame: function(frame) {

			if (this.options.frames != null && $type(frame) == 'string') {
				frame = this.options.frames[frame];
			}

			if (frame > this.options.framesPerMovie) {
				if (this.options.wrap) this.frame = 1;
				else this.frame = this.options.framesPerMovie;
			} else if (frame < 1) {
				if (this.options.wrap) this.frame = this.options.framesPerMovie;
				else this.frame = 1;
			} else {
				this.frame = frame;
			}
		},
		goto: function(frame) {
			this.setFrame(frame);
			var pos = this.computeFramePosition();
			this.element.setStyle('background-position', '-' + pos.left + 'px -' + pos.top + 'px');
			this.fireEvent('ENTER_FRAME', [this.movie, this.frame]);
			if (this.frame == this.options.framesPerMovie) this.fireEvent('MOVIE_FINISH', [ this.movie, this.frame ]);
		},
		computeFramePosition: function() {
			var movieOffset = this.movies.get(this.movie);
			var pos = {};
			pos.top = (movieOffset[0]-1) * this.options.frameSize[1];
			pos.left = ((this.options.framesPerMovie * this.options.frameSize[0]) * (movieOffset[1]-1)) + ((this.frame - 1) * this.options.frameSize[0]);
			return pos;
		}
	});

	gun.sprite.Animate = new Class({
		Extends: gun.sprite.Basic,
		options: {
			speed: 80,
			autoPlay: true,
			toRight: true,
			wrap: true
		},
		initialize: function(element, options) {
			this.parent(element, options);
			this.playTimer = null;
			if (this.options.autoPlay) this.play();
		},
		play: function() {
			if (this.playTimer == null) {
				this.playTimer = this.stepFrame.periodical( this.options.speed, this );
				this.fireEvent('PLAY', [this.movie, this.frame]);
			}
		},
		reverse: function() {
			this.options.toRight = !this.options.toRight;
			this.fireEvent('REVERSE', [this.movie, this.frame]);
			this.play();
		},

		stop: function() {
			if (this.playTimer) {
				this.playTimer = $clear(this.playTimer);
				this.fireEvent('STOP', [this.movie, this.frame]);
			}
		},
		stepFrame: function() {
			if (this.options.toRight) this.goto(this.frame + 1);
			else this.goto(this.frame - 1);
		}
	});

	gun.sprite.Button3 = new Class({
		Extends: gun.sprite.Basic,
		options: {
			/*
			onOver: $empty,
			onOut: $empty,
			onClick: $empty,
			*/
			wrap: false,
			movies: {'defaultButton':[1,1]},
			framesPerMovie: 3,
			initMovie: 'defaultButton',
			frames: {'normal':1, 'over':2, 'press':3},
			initFrame: 1
		},
		initialize: function(element, options) {
			this.parent(element, options);
			this.element.addEvents({
				'mouseenter': this.onOver.bindWithEvent(this),
				'mouseleave': this.onOut.bindWithEvent(this),
				'mouseup': this.onOver.bindWithEvent(this),
				'mousedown': this.onDown.bindWithEvent(this),
				'click': this.onClick.bindWithEvent(this),
			});
		},
		onOver: function(e) {
			this.goto('over');
			this.fireEvent('over', e);
		},
		onOut: function(e) {
			this.goto('normal');
			this.fireEvent('out', e);
		},
		onDown: function(e) {
			this.goto('press');
			this.fireEvent('down', e);
		},
		onClick: function(e) {
			this.fireEvent('click', e);
		}
	});
}